/*
=======================================================================

  Kamikazee - BOTS
  
=======================================================================
*/
#include "g_local.h"

#include "bots_game2cgame.h"

#include "bg_local.h"
#include "bots_local.h"
#include "bots_kamikazee.h"

void bots_updateClientData_kamikazee(gentity_t *self, bots_g2cg_kamikazee_t *p) {
	if (!self->client)
		return;

	BOTS_SETBIT(p->bits, self->client->qb_autorewireMode,	BOTS_G2CG_KAMIKAZEE_AUTOREWIRE);
	BOTS_SETBIT(p->bits, self->client->qb_longrangeMode,	BOTS_G2CG_KAMIKAZEE_LONGRANGE);
	BOTS_SETBIT(p->bits, self->client->qb_stickMode,		BOTS_G2CG_KAMIKAZEE_STICKMODE);

	p->weapons.gren1		= self->client->i_dettrap1;
	p->weapons.gren2		= self->client->i_dettrap2;
	p->weapons.grenademode	= self->client->qb_nukeMode;
	// Bah
	if (self->client->qb_detMode)
		p->weapons.weaponmode 	= 1;
	else if (self->client->qb_clusterMode)
		p->weapons.weaponmode 	= 2;
	else
		p->weapons.weaponmode 	= 0;
}

qboolean BOTS_nuke_think(gentity_t* self, gentity_t* other)
{
	if (Q_stricmp (self->classname, "nuke") != 0 || !other->client)
		return qtrue;

	if (level.time > self->i_proxTime || !self->parent)
	{
		G_ExplodeMissile(self);
		return qfalse;
	}

	if (other->bots_class == BOTS_KAMIKAZEE && 
		other->client->qb_autorewireMode)//	&&
		//self->parent != other)
	{
		int i;
		
		for(i = 0; i < level.maxclients; i++)
		{
			gentity_t* player = g_entities + i;

			if (!player->client)
				continue;
			if (!player->inuse)
				continue;
			if (!OnSameTeam (other, player))
				continue;
			
			if (player != other)
				BOTS_console(player->s.clientNum, va("%s is disabling a NUKE!", 
								other->client->pers.netname));
			else
				BOTS_cp_console(other->s.clientNum, "You are disabling a NUKE!");

		}

		G_FreeEntity( self );
		if (other->client->pers.classlevel <= 1)
			other->client->i_rewireTime = level.time + 3000;

		if (other->client->pers.classlevel == 2)
			other->client->i_rewireTime = level.time + 2000;

		if (other->client->pers.classlevel == 3)
			other->client->i_rewireTime = level.time + 1000;

		if (other->client->pers.classlevel == 4)
			other->client->i_rewireTime = 0;

		return qfalse;
	}

	//self->nextthink = level.time + FRAMETIME;
	return qfalse;
}

gentity_t *fire_clustergrenade (gentity_t *self, vec3_t start, vec3_t dir) 
{
    gentity_t       *bolt;

    VectorNormalize (dir);

    bolt = G_Spawn();
    bolt->classname = "cluster_grenade_child";
    bolt->nextthink = level.time + 2000;
    bolt->think = G_ExplodeMissile;
    bolt->s.eType = ET_MISSILE;
    bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
    bolt->s.weapon = WP_GRENADE_LAUNCHER;
    bolt->s.eFlags = EF_BOUNCE_HALF;

	// MANDATORY LINES!!!
    bolt->r.ownerNum = self->r.ownerNum;
    bolt->parent = self->parent;
	//////

    bolt->damage = 100;
    bolt->splashDamage = 100;
    bolt->splashRadius = 150;
    bolt->methodOfDeath = MOD_CLUSTER;
    bolt->splashMethodOfDeath = MOD_CLUSTER;
    bolt->clipmask = MASK_SHOT;

    bolt->s.pos.trType = TR_GRAVITY;
    bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;         // move a bit on the very first frame
    VectorCopy( start, bolt->s.pos.trBase );

    VectorScale( dir, 400, bolt->s.pos.trDelta );

    SnapVector( bolt->s.pos.trDelta );                      // save net bandwidth

    VectorCopy (start, bolt->r.currentOrigin);

    return bolt;
}

/////////////////////////////////////////////
//
// BOTS_cluster_explode
//
// Cluster grenades fire 4 other grenades out when the explode.
//
void BOTS_cluster_explode(gentity_t* self)
{
	vec3_t	dir;
	vec3_t	origin;

	vec3_t	grenade1;
	vec3_t  grenade2;
	vec3_t  grenade3;
	vec3_t  grenade4;

	BG_EvaluateTrajectory( &self->s.pos, level.time, origin );
	SnapVector( origin );
	G_SetOrigin( self, origin );

	// we don't have a valid direction, so just point straight up
	dir[0] = dir[1] = 0;
	dir[2] = 1;

	self->s.eType = ET_GENERAL;
	G_AddEvent( self, EV_MISSILE_MISS, DirToByte( dir ) );

	self->freeAfterEvent = qtrue;

	
	// splash damage
	if ( self->splashDamage )
		G_RadiusDamage( self->r.currentOrigin, self->parent, self->splashDamage, self->splashRadius, NULL, self->splashMethodOfDeath );

/*	VectorSet(grenade1,  20,  20, 40);
	VectorSet(grenade2, -20,  20, 40);
	VectorSet(grenade3,  20, -20, 40);
	VectorSet(grenade4, -20, -20, 40);
*/
	VectorSet(grenade1,  5,  5, 40);
	VectorSet(grenade2,  -5,  5, 40);
	VectorSet(grenade3,  5, -5, 40);
	VectorSet(grenade4, -5, -5, 40);
        
	// We must call to a slightly different function than fire_grenade.  fire_grenade
	// assumes self is a client so when it fills in the ownernum and the parent it will crash
	// if we don't modify it a bit.
	fire_clustergrenade (self, origin, grenade1);
	fire_clustergrenade (self, origin, grenade2);
	fire_clustergrenade (self, origin, grenade3);
	fire_clustergrenade (self, origin, grenade4);

	trap_LinkEntity( self );
}

/////////////////////////////////////////////
//
// BOTS_settrap
//
// This function specifies which dettrap our detpipes will go into
//
void BOTS_settrap(int clientNum, int settrapNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use detpipes
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee gets dettraps.");
		return;
	}

	if (settrapNum == 2)
	{
		ent->client->qb_settrap2 = qtrue;
		ent->client->qb_settrap1 = qfalse;
	}
	else if (settrapNum == 1)
	{
		ent->client->qb_settrap1 = qtrue;
		ent->client->qb_settrap2 = qfalse;
	}
	else
	{
		ent->client->qb_settrap1 = qfalse;
		ent->client->qb_settrap2 = qfalse;
	}
}

/////////////////////////////////////////////
//
// BOTS_dettrap
//
// This function will run through the specified dettrap and change its nextthink
// time so that it detonates immediately.
//
void BOTS_dettrap(int clientNum, int dettrapNum)
{
	gentity_t*	ent = g_entities + clientNum;
	gentity_t*	grenade = NULL;
	char		grenade_name[30];

	if (!ent->client)
		return;

	// check to see if this class can use detpipes
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee gets dettraps.");
		return;
	}

	if (dettrapNum == 1)
	{
		if (ent->client->i_dettrap1 == 0)
		{
			//BOTS_cp_console(clientNum, "You have no detpipes for this trap.");
			return;
		}

		strcpy(grenade_name, "dettrap1");
	}
	else if (dettrapNum == 2)
	{
		if (ent->client->i_dettrap2 == 0)
		{
			//BOTS_cp_console(clientNum, "You have no detpipes for this trap.");
			return;
		}
		strcpy(grenade_name, "dettrap2");
	}
	else
		return;

	// find all grenades labled dettrapX (X = 1 or 2)
	while ((grenade = G_Find (grenade, FOFS(classname), grenade_name)) != NULL)
	{
		if(grenade->r.ownerNum == clientNum)
		{
			grenade->nextthink = level.time + 5;

			// remove the grenade from the total
			if (dettrapNum == 1 && ent->client->i_dettrap1)
				ent->client->i_dettrap1--;
			else if (dettrapNum == 2 && ent->client->i_dettrap2)
				ent->client->i_dettrap2--;
		}
	}

}

/////////////////////////////////////////////
//
// BOTS_longrange
//
// This function toggles the longrange grenade launcher
//
void BOTS_longrange(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use longrange
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can use longrange.");
		return;
	}

	if (ent->client->pers.classlevel < 3)
	{
		BOTS_cp_console(clientNum, "You must be at least level 3 to use longrange.");
		return;
	}

	ent->client->qb_longrangeMode = !ent->client->qb_longrangeMode;

	/*
	if (ent->client->qb_longrangeMode)
		BOTS_cp_console(clientNum, "Longrange grenades activated.");
	else
		BOTS_cp_console(clientNum, "Longrange grenades deactivated.");
	*/
}

/////////////////////////////////////////////
//
// BOTS_normal
//
// This function puts the player in normal grenade mode
//
void BOTS_normal(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use normal
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can use normal.");
		return;
	}

	if (ent->client->qb_normalMode)
		return;

	ent->client->qb_normalMode = qtrue;

	ent->client->qb_detMode		= qfalse;
	ent->client->qb_clusterMode	= qfalse;

	if (ent->client->qb_normalMode)
		BOTS_cp_console(clientNum, "Normal grenades activated.");
}

/////////////////////////////////////////////
//
// BOTS_dettog
//
// This function is only used when hitting the use grenade launcher key
// and you already have the grenade launcher armed.
//
void BOTS_dettog(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	ent->client->qb_detMode = !ent->client->qb_detMode;

	if (ent->client->qb_detMode)
		BOTS_cp_console(clientNum, "Detpipes activated.");
	else
		BOTS_cp_console(clientNum, "Detpipes deactivated.");
}

/////////////////////////////////////////////
//
// BOTS_detmode
//
// This function puts the user in detpipe mode
//
void BOTS_detmode(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use detmode
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can use detmode.");
		return;
	}

	if (ent->client->qb_detMode)
		return;

	ent->client->qb_detMode = qtrue;

	//ent->client->qb_clusterMode	= qfalse;
	ent->client->qb_normalMode	= qfalse;

	/*
	if (ent->client->qb_detMode)
		BOTS_cp_console(clientNum, "Detpipes activated.");
	*/
}

/////////////////////////////////////////////
//
// BOTS_cluster
//
// This function toggles cluster grenades
//
void BOTS_cluster(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use clusters
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can use clusters.");
		return;
	}

	if (ent->client->pers.classlevel < 2)
	{
		BOTS_cp_console(clientNum, "You must be at least level 2 to use clusters.");
		return;
	}

	if (ent->client->qb_clusterMode)
		return;

	ent->client->qb_clusterMode = qtrue;

	ent->client->qb_detMode		= qfalse;
	ent->client->qb_normalMode	= qfalse;

	/*
	if (ent->client->qb_clusterMode)
		BOTS_cp_console(clientNum, "Cluster grenades activated.");
	*/
}

/////////////////////////////////////////////
//
// BOTS_stickmode
//
// This function toggles sticky grenades
//
void BOTS_stickmode(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use sticky grenades
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can use sticky grenades.");
		return;
	}

	if (ent->client->pers.classlevel < 2)
	{
		BOTS_cp_console(clientNum, "You must be at least level 2 to use sticky grenades.");
		return;
	}

	ent->client->qb_stickMode = !ent->client->qb_stickMode;

	/*
	if (ent->client->qb_stickMode)
		BOTS_cp_console(clientNum, "Sticky grenades activated.");
	else
		BOTS_cp_console(clientNum, "Sticky grenades deactivated.");
	*/
}

/////////////////////////////////////////////
//
// BOTS_autorewire
//
// This function toggles autorewire
//
void BOTS_autorewire(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use autorewire
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can autorewire.");
		return;
	}

	ent->client->qb_autorewireMode = !ent->client->qb_autorewireMode;

	/*
	if (ent->client->qb_autorewireMode)
		BOTS_cp_console(clientNum, "Autorewire activated.");
	else
		BOTS_cp_console(clientNum, "Autorewire deactivated.");
	*/
}

void BOTS_suicide(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;
	int			modifier = 1;

	if (!ent->client)
		return;

	// check to see if this class can use suicide
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee can suicide.");
		return;
	}

	G_Damage( ent, ent, ent, NULL, ent->s.pos.trBase, 10000, 0, MOD_SUICIDE);

	//G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( ent->movedir ) );
	G_AddEvent( ent, EV_BOTS_GIB_SUICIDE, DirToByte( ent->movedir ) );

	if (ent->client->pers.classlevel > 1)
		modifier = ent->client->pers.classlevel;
	G_RadiusDamage (ent->s.pos.trBase, ent, 
					modifier * modifier * ent->client->ps.ammo[WP_GRENADE_LAUNCHER],
					150, NULL, MOD_GRENADE);
	
	trap_LinkEntity( ent );
}

void BOTS_nuke(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;

	if (!ent->client)
		return;

	// check to see if this class can use suicide
	if (ent->bots_class != BOTS_KAMIKAZEE)
	{
		BOTS_cp_console(clientNum, "Only the Kamikazee gets a nuke.");
		return;
	}

	if (ent->client->pers.classlevel < 3)
	{
		BOTS_cp_console(clientNum, "You must be at least level 3 to use the nuke.");
		return;
	}

	ent->client->qb_nukeMode = qtrue;
	/*
	BOTS_cp_console(clientNum, "Nuke enabled.");
	*/
}

/////////////////////////////////////////////
//
// BOTS_KamikazeeCommands
//
// This will parse the passed cmd string and call to the correct functions.
// 
// RETURNS
//    qfalse : cmd is not a kamikazee command
//	  qtrue	 : cmd is a kamikazee command
//
qboolean BOTS_KamikazeeCommands(int clientNum, char* cmd)
{
	if (Q_stricmp (cmd, "detmode") == 0 )
	{
		BOTS_detmode(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "dettrap1") == 0 )
	{
		BOTS_dettrap(clientNum, 1);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "dettrap2") == 0 )
	{
		BOTS_dettrap(clientNum, 2);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "settrap0") == 0 )
	{
		BOTS_settrap(clientNum, 0);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "settrap1") == 0 )
	{
		BOTS_settrap(clientNum, 1);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "settrap2") == 0 )
	{
		BOTS_settrap(clientNum, 2);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "longrange") == 0 )
	{
		BOTS_longrange(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "normal") == 0 )
	{
		BOTS_normal(clientNum);
		return qtrue;
	}	
	else if (Q_stricmp (cmd, "detmode") == 0 )
	{
		BOTS_detmode(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "dettog") == 0 )
	{
		BOTS_dettog(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "cluster") == 0 )
	{
		BOTS_cluster(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "autorewire") == 0 )
	{
		BOTS_autorewire(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "stickmode") == 0 )
	{
		BOTS_stickmode(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "suicide") == 0 )
	{
		BOTS_suicide(clientNum);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "nuke") == 0 )
	{
		BOTS_nuke(clientNum);
		return qtrue;
	}

	return qfalse;
}

/////////////////////////////////////////////
//
// BOTS_ClientThink_kamikazee
//
// Kamikazee think routine.  Called once for each client think if
// the client is an kamikazee.
//
void BOTS_ClientThink_kamikazee(gentity_t* ent)
{
	if (ent->health <= 0)
		return;
}
